#include <fstream>
#include "game.hpp"
#include "game.hpp"
#include "texture_manager.hpp"


void Game::init(const char *title, int width, int height, bool fullscreen, int x_pos, int y_pos)
{
    int flags = fullscreen ? SDL_WINDOW_FULLSCREEN : 0;
    std::string bricks_file_path = "assets/levels/level_1.txt";

    std::ifstream level_file(bricks_file_path);

    if (SDL_Init(SDL_INIT_EVERYTHING) == 0)
    {
        window = SDL_CreateWindow(title, x_pos, y_pos, width, height, flags);
        if (window == nullptr)
        {
            std::cout << "Window could not be created! SDL_Error: " << SDL_GetError() << "\n";
            is_running = false;
            return;
        }

        renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
        if (renderer == nullptr)
        {
            std::cout << "Renderer could not be created! SDL_Error: " << SDL_GetError() << "\n";
            is_running = false;
            return;
        }
        SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF);
        if (IMG_Init(IMG_INIT_JPG | IMG_INIT_PNG) == 0)
        {
            std::cout << "SDL_image could not be initialized! SDL_Error: " << IMG_GetError << "\n";
            is_running = false;
            return;
        }
        std::cout << "Successfully initialized game!\n";
        is_running = true;

      

        TextureManager::get_instance()->load_texture("assets/platform.png", "platform", renderer);
        TextureManager::get_instance()->load_texture("assets/bricks.png", "bricks", renderer);
        TextureManager::get_instance()->load_texture("assets/ball.png", "ball", renderer);
        
        if (level_file.good())
        {
            int brick_type, brick_count = 0;
            bricks = new BrickTileMap("bricks", renderer, 10, 128, 64);
            while (level_file >> brick_type)
            {
                bricks->push_back_brick(renderer, brick_type);
            }
        }
        level_file.close();
        int platform_dst_w = width / 7;
        int platform_dst_h = height / 25;
        int platform_x_pos = width / 2 - width / 14;
        int platform_y_pos = height - 50;

        platform = new Platform("platform", "ball", renderer, platform_x_pos, platform_y_pos, 128, 16, 8);
        platform->set_size(platform_dst_w, platform_dst_h);

        int ball_dst_w = platform_dst_w / 7;
        int ball_x_pos = platform_x_pos + platform_dst_w / 2 - ball_dst_w / 2;
        int ball_y_pos = platform_y_pos - 10 - ball_dst_w;

        ball = new Ball("ball", renderer, ball_x_pos, ball_y_pos, 8, 8);
        ball->set_size(ball_dst_w, ball_dst_w);
    }
    else
    {
        std::cout << "SDL could not be initialized! SDL_Error: " << SDL_GetError << "\n";
        is_running = false;
        return;
    }
}

void Game::handle_input()
{
    SDL_Event e;
    SDL_PollEvent(&e);

    if (e.type == SDL_QUIT)
        is_running = false;

    if (ball != nullptr)
        ball->handle_input(e);

    if (platform != nullptr)
        platform->handle_input(e);
}
void Game::update()
{
    if (platform != nullptr)
        platform->update();

    if (platform != nullptr)
    {
        if (bricks != nullptr && ball != nullptr)
        {
            for (int i = 0; i < bricks->get_brick_count(); i++)
            {
                int closest_point_x = 0;
                int closest_point_y = 0;

                Brick* brick = bricks->get_brick_at_index(i);
                if (ball->check_collision(*brick, closest_point_x, closest_point_y))
                {

                    ball->handle_brick_collision(*brick, closest_point_x, closest_point_y);

                    bricks->destroy_brick_at_index(i);
                    break; //Break loop to prevent collisions with multiple bricks within the same frame
                }
            }
            ball->update(*platform);
            if (ball->is_out_of_bounds())
            {
                std::cout << "failed failed failed failed" << "\n";
                //failed = true;
            }
            else if (!bricks->get_brick_count())
            {
                std::cout << "completed completed completed completed" << "\n";
                //completed = true;
            }
        }
    }
    
}

void Game::render()
{
    SDL_RenderClear(renderer);
    //The entities that should be rendered on top have to be last


    if (platform != nullptr)
        platform->render();

    if (bricks != nullptr)
        bricks->render();

    if (ball != nullptr)
        ball->render();

    SDL_RenderPresent(renderer);
}

void Game::clean()
{
    TextureManager::clean_instance();

    delete platform;
    platform = nullptr;

    if (bricks != nullptr)
        delete bricks;


    SDL_DestroyRenderer(renderer);
    renderer = nullptr;

    SDL_DestroyWindow(window);
    window = nullptr;

    SDL_Quit();
    std::cout << "Game exited by user\n";
}